3.9 Виджеты. Container Особенности
2 из 2 шагов пройдено

 Виджеты. Container Особенности

➡️ Ссылка на репозиторий с кодом этого урока

Container Особенности Поведения

❗️Изучение материала требует подготовки

К этой теме следует вернуться после изучения базовых виджетов и после самостоятельной верстки нескольких простых макетов.

Файл main.dart

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "Flutter Course",
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
      ),
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true, 
          title: const Text("Виджет Container"),
        ),
        body: ContainerExample() // 🡰 Сюда
      ),
    );
  }
}

Создание базового контейнера

Добавим в папку widgets файл ex_container.dart

Виджет Container

Это универсальный строительный виджет во Flutter, который позволяет гибко управлять внешним видом элементов, как блок <div> в веб-разработке. Container объединяет в себе возможности настройки фона, размеров, позиционирования, отступов и границ.

Container вмещает только одного дочернего элемента child, но этот элемент может содержать другие компоненты, создавая сложные иерархии.

Container это блочный элемент, по сути прямоугольник с определенными свойствами, такими как цвет фона, границы и отступы (внутренние и внешние).

Для создания базового контейнера, мы можем определить несколько свойств, таких как colorwidthheightpadding и margin. Например, создадим контейнер с голубым фоном, шириной 200 и высотой 200

Container(
  color: Colors.blue,
  width: 200,
  height: 200,
)

Основные свойства

alignment → выравнивание ДОЧЕРНЕГО элемента
child → дочерний элемент
color → цвет фона контейнера (не использовать если задан параметр decoration)
constraints → дополнительные ограничения размера для ДОЧЕРНЕГО элемента
decoration → фоновое оформление контейнера
foregroundDecoration → поверхностное оформление, рисуется поверх child
width → ширина контейнера
height → высота контейнера
margin → отступы вокруг контейнера
padding → поля внутри контейнера
transform → матричное преобразование геометрии контейнера

Добавление границ
Можно добавить границы к контейнеру с помощью свойства border

import 'package:flutter/material.dart';

class ContainerExample extends StatelessWidget {
  const ContainerExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        // Ошибка! Нельзя одновременно использовать color и decoration
        // color: Colors.blue,
        width: 200,
        height: 200,
        decoration: BoxDecoration(
          color: Colors.blue,
          border: Border.all(
            // Добавить границы со всех сторон
            color: Colors.black,
            width: 5,
          ),
        ),
      ),
    );
  }
}

Важно! 
При использовании BoxDecoration, цвет фона color задается внутри свойства decoration, а не в color контейнера!!! Иначе будет ошибка отрисовки

Добавление отступов

Можно добавить отступы к контейнеру, с помощью свойств paddingили margin

Сделаем контейнер с фоном, шириной 200, высотой 200 и с отступами по 20 пикселей

class ContainerExample extends StatelessWidget {
  const ContainerExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 200,
      height: 200,

      // Внешние отступы от границ контейнера
      margin: const EdgeInsets.all(20.0),
      // Внутренние отступы от содержимого
      padding: const EdgeInsets.all(20.0),

      decoration: BoxDecoration(
        color: Colors.blue,
        border: Border.all(color: Colors.black, width: 5),
      ),
      child: const Text(
        "Container",
        style: TextStyle(
          color: Colors.white,
          fontSize: 18.0,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
}

 

Рассмотрим подробно все параметры виджета для создания отступов:

// Задать одинаковые отступы со всех сторон
padding: const EdgeInsets.all(20.0),

// Задать отступы конкретно для каждой стороны
// Следование такое: Left, Top, Right, Bottom
padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),

// Задать отступ конкретно для какой-то стороны, или нескольких сторон
padding: const EdgeInsets.only(top: 20.0),
padding: const EdgeInsets.only(right: 20.0),
padding: const EdgeInsets.only(bottom: 20.0),
padding: const EdgeInsets.only(left: 20.0),

// Задать отступы симметрично горизонтально или вертикально
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),

Примеры поведения Container

1 - Контейнер занимает всё доступное пространство

Контейнер занимает доступное ему пространство

  • Контейнер растянется до родителя, если у него нет child
  • Если родитель это Scaffold, то размер будет на весь экран
  • Если у родителя есть свои размеры, то до размеров этого родителя
class ContainerExample1 extends StatelessWidget {
  const ContainerExample1({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(color: Colors.blue[100]);

    // Размеры родителя 150 на 150
    // body: SizedBox(
    //   width: 150,
    //   height: 150,
    //   child: Container(
    //     color: Colors.blue[100],
    //   ),
    // ),
  }
}

2 - Контейнер принимает размер дочернего элемента

Контейнер принимает размер дочернего элемента.

Если у Container нет родителя, но есть child, то Container ужмётся до размеров своего child

class ContainerExample2 extends StatelessWidget {
  const ContainerExample2({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Colors.blue[100],
        child: const Text(
          'IT-Квантум',
          style: TextStyle(fontSize: 40.0, fontWeight: FontWeight.bold),
        ),
      ),
    );
  }
}

3 - Контейнер принимает размеры ограничений

Высоту и ширину можно регулировать вручную

  • Размеры контейнера 100% по отношению к родительскому элементу

  • Если Родитель не указывает ограничения размеров, то

    • Если Container имеет child, то он ужимается до него
    • Если Container имеет height и width, то он применяет эти значения
  • Если Родитель указывает ограничения размеров, то Container принимает эти размеры, даже если внутри Container указаны вручную значения width и height

Вариант 1 - когда у Container нет родителя, но есть свои width height и child

class ContainerExample3 extends StatelessWidget {
  const ContainerExample3({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      // Высоту и ширину можно регулировать вручную
      width: double.infinity, // Макс. возможная ширина
      height: 200.0,
      color: Colors.blue[100],
      child: const Text(
        'IT-Квантум',
        style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
      ),
    );
  }
}

Вариант 2 - когда у Container есть родитель со своими ограничениями размеров.
Так же у Container есть свои width height и child

class ContainerExample3 extends StatelessWidget {
  const ContainerExample3({super.key});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      // Приоритет размеров родителя выше чем у вложенных виджетов
      width: 150.0,
      height: 100.0,
      child: Container(
        width: double.infinity, // Игнор этого размера
        height: 200.0, // Игнор этого размера
        color: Colors.blue[100],
        child: const Text(
          'IT-Квантум',
          style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
        ),
      ),
    );
  }
}

4 - Выравнивание дочернего элемента контейнера

Alignment - eсли добавить для child контейнера выравнение (alignment), то контейнер растянется до своего родителя !

Расположение по умолчанию - если Alignment не указано, child всегда будет располагаться в верхнем-левом углу контейнера

class ContainerExample4 extends StatelessWidget {
  const ContainerExample4({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      // Ширина контейнера 100% родителя
      width: double.infinity,
      height: 200.0,
      // Дочерний элемент по центру
      alignment: Alignment.center,
      color: Colors.blue[100],
      child: const Text('IT-Квантум'),
    );
  }
}

Поведение работы выравнивания

На 1 изображении у контейнера ЕСТЬ width и heightуказано alignment
На 2 изображении у контейнера НЕТ width и heightуказано alignment
На 3 изображении у контейнера ЕСТЬ width и heightНЕ указано alignment

Значения Alignment

Alignment имеет несколько положений где может находится child
Можно более точно указать положение через координаты, например
Alignment(-1,1)
Alignment(-0.1,1)
Alignment(0.02,-0.5)

 

5 - Контейнер с максимальной шириной, отступами и фоном

Единицы размеров Flutter виджетов

Размеры элементов, такие как ширина и высота, указываются в logical pixels логических пикселях

height: 200.0

Логические пиксели - это абстрактная единица измерения, которая позволяет создавать интерфейсы, которые выглядят одинаково на устройствах с разными плотностями пикселей.

Логические пиксели автоматически масштабируются в зависимости от плотности пикселей устройства, на котором работает приложение.

Например, на устройстве с плотностью пикселей 1x (например, старые смартфоны) 200 логических пикселей будут соответствовать 200 физическим пикселям. На устройстве с плотностью пикселей 2x (например, современные смартфоны) 200 логических пикселей будут соответствовать 400 физическим пикселям, и так далее.

class ContainerExample5 extends StatelessWidget {
  const ContainerExample5({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity, // Ширина контейнера 100% родителя
      height: 200.0, // Высота контейнера 100

      padding: const EdgeInsets.all(32.0), // внутренние отступы
      margin: const EdgeInsets.all(32.0), // внешние отступы

      color: Colors.blue[100], // Цвет фона контейнера
      child: const Text(
        'IT-Квантум',
        style: TextStyle(fontSize: 24.0, fontWeight: FontWeight.bold),
      ),
    );
  }
}

6 - Фоновое изображение контейнера

class ContainerExample6 extends StatelessWidget {
  const ContainerExample6({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        width: 250.0,
        height: 250.0,
        alignment: Alignment.bottomRight,

        // Установить фоном изображение
        decoration: const BoxDecoration(
          image: DecorationImage(image: AssetImage("assets/images/driada.png")),

          // Сделать фигуру контейнера в виде круга
          // shape: BoxShape.circle,
        ),

        child: const Text(
          'IT-Квантум в деле',
          style: TextStyle(color: Colors.white, fontSize: 16.0),
        ),
      ),
    );
  }
}

Ключевые моменты поведения виджета Container

Ключевые моменты

  • Контейнер БЕЗ ДОЧЕРНЕГО элемента, и БЕЗ ОГРАНИЧЕНИЙ по ширине и высоте, занимает ВСЁ доступное пространство (на которое позволяет занять его родитель)

  • Контейнер С ДОЧЕРНИМ элементом принимает ЕГО размер (точней выразится дочерний элемент может принимать размер, ограниченный container, а раз у Container нет ограничений, то по сути размер будут как у child)

  • НО если ЕСТЬ ВЫРАВНИВАНИЕ, то принимает РАЗМЕР РОДИТЕЛЬСКОГО элемента.

  • Параметры widthheight и constraints переопределяют размер контейнера.

  • Если у виджета нет дочернего элемента, нет высоты, ширины, ограничений, а родительский элемент предоставляет неограниченные ограничения, тогда Контейнер пытается уменьшиться до как можно меньшего значения.

  • Если у виджета нет дочернего элемента и нет выравнивания, но есть высота, ширина или ограничения, тогда Контейнер пытается быть как можно меньше с учетом комбинации этих ограничений и ограничений родительского элемента.

  • Если виджет не имеет дочернего элемента, высоты, ширины, ограничений и выравнивания, но родительский элемент предоставляет ограниченные ограничения, тогда Контейнер расширяется, чтобы соответствовать ограничениям, предоставленным родительским элементом.

  • Если у виджета есть выравнивание, а родительский элемент предоставляет неограниченные ограничения, тогда Контейнер пытается установить размер вокруг дочернего элемента.

  • Если у виджета есть выравнивание, а родительский элемент предоставляет ограниченные ограничения, тогда Контейнер пытается развернуться, чтобы соответствовать родителю, а затем размещает дочерний элемент внутри себя в соответствии с выравниванием.

  • Если у виджета есть дочерний элемент, но нет высоты, ширины, ограничений и выравнивания, то Контейнер передает ограничения от родительского элемента дочернему и размеры самого себя в соответствии с дочерним элементом.


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий